package com.sirun.ble.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

/**
 * @author : hzw
 */
public class AwDateUtil {

    /**
     * 1s==1000ms
     */
    private final static int TIME_MILLISECONDS = 1000;
    /**
     * 时间中的分、秒最大值均为60
     */
    private final static int TIME_NUMBERS = 60;
    /**
     * 时间中的小时最大值
     */
    private final static int TIME_HOURSES = 24;
    /**
     * 格式化日期的标准字符串
     */
    public final static String FORMAT_YMD_HMS = "yyyy-MM-dd HH:mm:ss";
    public final static String FORMAT_YMD_HM = "yyyy-MM-dd HH:mm";
    public final static String FORMAT_YMD = "yyyy-MM-dd";

    private static final String[] MONTH_EN = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

    /**
     * 获取时区信息
     */
    public static TimeZone getTimeZone() {
        return TimeZone.getDefault();
    }

    /**
     * 将日期字符串转换为Date对象, 默认样式YMD_HMS
     *
     * @param date 日期字符串，必须为"yyyy-MM-dd HH:mm:ss"
     * @return 日期字符串的Date对象表达形式
     */
    public static Date parseDefaultFormatDate(String date) {
        return parseDate(date, FORMAT_YMD_HMS);
    }

    /**
     * 将日期字符串转换为Date对象
     *
     * @param date   日期字符串，必须为"yyyy-MM-dd HH:mm:ss"
     * @param format 格式化字符串
     * @return 日期字符串的Date对象表达形式
     */
    public static Date parseDate(String date, String format) {
        Date dt = null;
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        try {
            dt = dateFormat.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return dt;
    }

    /**
     * 将Date对象转换为指定格式的字符串, 默认返回格式 YMD_HMS
     *
     * @param date Date对象
     * @return Date对象的字符串表达形式"yyyy-MM-dd HH:mm:ss"
     */
    public static String formatDate(Date date) {
        if (date == null) {
            return "";
        }
        return formatDate(date, FORMAT_YMD_HMS);
    }

    /**
     * 将Date对象转换为指定格式的字符串
     *
     * @param date   Date对象
     * @param format 格式化字符串
     * @return Date对象的字符串表达形式
     */
    public static String formatDate(Date date, String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        return dateFormat.format(date);
    }

    /**
     * 将Date对象转换为指定格式的字符串
     * @param date
     * @param simpleDateFormat 格式化样式, 单独提供, 方便适配外国日期样式
     * @return
     */
    public static String formatDate(Date date, SimpleDateFormat simpleDateFormat) {
        return simpleDateFormat.format(date);
    }

    /**
     * 格式化unix时间戳日期, 默认返回格式 YMD_HMS
     *
     * @param unixTime unix时间戳
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    public static String formatUnixTime(String unixTime) {
        if (AwDataUtil.isEmpty(unixTime)) {
            return "";
        }
        return formatUnixTime(AwDataUtil.getLongValue(unixTime), FORMAT_YMD_HMS);
    }

    /**
     * 格式化unix时间戳日期, 默认返回格式 YMD_HMS
     *
     * @param unixTime unix时间戳 1970-01-01T00:00:00Z.
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    public static String formatUnixTime(long unixTime) {
        return formatUnixTime(unixTime, FORMAT_YMD_HMS);
    }


    /**
     * 格式化unix时间戳日期
     *
     * @param unixTime unix时间戳
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    public static String formatUnixTime(String unixTime, String format) {
        if (AwDataUtil.isEmpty(unixTime)) {
            return "";
        }
        return formatUnixTime(AwDataUtil.getLongValue(unixTime), format);
    }

    /**
     * 格式化unix时间戳日期
     *
     * @param unixTime unix时间戳
     * @param format   格式化字符串
     * @return 日期字符串
     */
    public static String formatUnixTime(long unixTime, String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        return dateFormat.format(unixTime);
    }

    /**
     * 将GMT日期格式化为系统默认时区的日期字符串表达形式
     *
     * @param gmtUnixTime GTM时间戳
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    public static String formatGMTUnixTime(long gmtUnixTime) {
        return formatGMTUnixTime(gmtUnixTime, FORMAT_YMD_HMS);
    }

    /**
     * 将GMT日期格式化为系统默认时区的日期字符串表达形式
     *
     * @param gmtUnixTime GTM时间戳
     * @param format      格式化字符串
     * @return 日期字符串"yyyy-MM-dd HH:mm:ss"
     */
    public static String formatGMTUnixTime(long gmtUnixTime, String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        return dateFormat.format(gmtUnixTime + TimeZone.getDefault().getRawOffset());
    }

    /**
     * 获取时间戳的Date表示形式
     *
     * @param unixTime unix时间戳
     * @return Date对象
     */
    public static Date getUnixDate(long unixTime) {
        return new Date(unixTime);
    }

    /**
     * 获取GMT时间戳的Date表示形式（转换为Date表示形式后，为系统默认时区下的时间）
     *
     * @param gmtUnixTime GMT Unix时间戳
     * @return Date对象
     */
    public static Date getGMTDate(long gmtUnixTime) {
        return new Date(gmtUnixTime + TimeZone.getDefault().getRawOffset());
    }

    /**
     * 将系统默认时区的Unix时间戳转换为GMT Unix时间戳
     *
     * @param unixTime unix时间戳
     * @return GMT Unix时间戳
     */
    public static long getGMTUnixTime(long unixTime) {
        return unixTime - TimeZone.getDefault().getRawOffset();
    }

    /**
     * 将GMT Unix时间戳转换为系统默认时区的Unix时间戳
     *
     * @param gmtUnixTime GMT Unix时间戳
     * @return 系统默认时区的Unix时间戳
     */
    public static long getCurrentTimeZoneUnixTime(long gmtUnixTime) {
        return gmtUnixTime + TimeZone.getDefault().getRawOffset();
    }

    /**
     * 获取当前时间的GMT Unix时间戳
     *
     * @return 当前的GMT Unix时间戳
     */
    public static long getGMTUnixTimeByCalendar() {
        Calendar calendar = Calendar.getInstance();
        // 获取当前时区下日期时间对应的时间戳
        long unixTime = calendar.getTimeInMillis();
        // 获取标准格林尼治时间下日期时间对应的时间戳
        long unixTimeGMT = unixTime - TimeZone.getDefault().getRawOffset();
        return unixTimeGMT;
    }

    /**
     * 获取当前时间的Unix时间戳
     *
     * @return 当前的Unix时间戳
     */
    public static long getUnixTimeByCalendar() {
        Calendar calendar = Calendar.getInstance();
        // 获取当前时区下日期时间对应的时间戳
        long unixTime = calendar.getTimeInMillis();
        return unixTime;
    }

    /**
     * 获取更改时区后的时间
     *
     * @param date    时间
     * @param oldZone 旧时区
     * @param newZone 新时区
     * @return 时间
     */
    public static Date getChangeZoneTime(Date date, TimeZone oldZone, TimeZone newZone) {
        Date dateTmp = null;
        if (date != null) {
            int timeOffset = oldZone.getRawOffset() - newZone.getRawOffset();
            dateTmp = new Date(date.getTime() - timeOffset);
        }
        return dateTmp;
    }

    /**
     * 将总秒数转换为时分秒表达形式
     *
     * @param seconds 任意秒数
     * @return %s小时%s分%s秒
     */
    public static String formatTime(long seconds) {
        long hh = seconds / TIME_NUMBERS / TIME_NUMBERS;
        long mm = (seconds - hh * TIME_NUMBERS * TIME_NUMBERS) > 0 ? (seconds - hh * TIME_NUMBERS * TIME_NUMBERS) / TIME_NUMBERS : 0;
        long ss = seconds < TIME_NUMBERS ? seconds : seconds % TIME_NUMBERS;
        return (hh == 0 ? "" : (hh < 10 ? "0" + hh : hh) + "小时")
                + (mm == 0 ? "" : (mm < 10 ? "0" + mm : mm) + "分")
                + (ss == 0 ? "" : (ss < 10 ? "0" + ss : ss) + "秒");
    }

    /**
     * 获取当前时间距离指定日期时差的大致表达形式
     *
     * @param date 日期
     * @return 时差的大致表达形式
     */
    public static String getDiffTimeDesc(long date) {
        String strTime = "很久很久以前";
        long time = Math.abs(new Date().getTime() - date);
        // 一分钟以内
        if (time < TIME_NUMBERS * TIME_MILLISECONDS) {
            strTime = "刚刚";
        } else {
            int min = (int) (time / TIME_MILLISECONDS / TIME_NUMBERS);
            if (min < TIME_NUMBERS) {
                if (min < 15) {
                    strTime = "一刻钟前";
                } else if (min < 30) {
                    strTime = "半小时前";
                } else {
                    strTime = "1小时前";
                }
            } else {
                int hh = min / TIME_NUMBERS;
                if (hh < TIME_HOURSES) {
                    strTime = hh + "小时前";
                } else {
                    int days = hh / TIME_HOURSES;
                    if (days <= 6) {
                        strTime = days + "天前";
                    } else {
                        int weeks = days / 7;
                        if (weeks < 3) {
                            strTime = weeks + "周前";
                        }
                    }
                }
            }
        }

        return strTime;
    }

    /**
     * 获取当天0点时间戳
     * @return
     */
    public static long getTodayZeroTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 判断传入时间字符串  是否是当天
     * @param dateStr
     * @return
     */
    public static boolean isToday(String dateStr) {
        if (dateStr == null) {
            return false;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("MMMM dd,yyyy");
        dateStr = sdf.format(new Date(Long.valueOf(dateStr)));
        String dateStrCurrent = sdf.format(new Date());
        if (dateStr != null && dateStrCurrent != null && dateStr.equals(dateStrCurrent))
            return true;
        return false;
    }

    /**
     * 功能：判断日期是否和当前date对象在同一天。
     * 参见：http://www.cnblogs.com/myzhijie/p/3330970.html
     *
     * @param date 比较的日期
     * @return boolean 如果在返回true，否则返回false。
     */
    public static boolean isSameDay(Date date) {
        if (date == null) {
            throw new IllegalArgumentException("date is null");
        }
        Calendar nowCalendar = Calendar.getInstance();
        Calendar newCalendar = Calendar.getInstance();
        newCalendar.setTime(date);
        return (nowCalendar.get(Calendar.ERA) == newCalendar.get(Calendar.ERA) &&
                nowCalendar.get(Calendar.YEAR) == newCalendar.get(Calendar.YEAR) &&
                nowCalendar.get(Calendar.DAY_OF_YEAR) == newCalendar.get(Calendar.DAY_OF_YEAR));
    }


    /**
     * 获取当前时间前12个月集合
     * @return
     */
    public static List<String> getPreMonthList(String format) {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 12; i++) {
            list.add(getFormatSpecDate(System.currentTimeMillis(), Calendar.MONTH, -i, format));
        }
        Collections.reverse(list);
        return list;
    }

    /**
     * 时间转换, 秒转换为 时分秒显示
     * @param secondsTime
     * @return
     */
    public static String convertTimeToHms(String secondsTime) {
        if (AwDataUtil.isEmpty(secondsTime)) {
            return "";
        }
        int seconds = Integer.parseInt(secondsTime);
        String timeStr = null;
        int hour = 0;
        int minute = 0;
        int second = 0;

        minute = seconds / 60;
        if (minute < 60) {
            second = seconds % 60;
            if (second == 0) {
                if (minute == 0) {
                    timeStr = "0";
                } else {
                    timeStr = minute + "m";
                }
            } else {
                if (minute == 0) {
                    if (second == 0) {
                        timeStr = "0";
                    } else {
                        timeStr = second + "s";
                    }
                } else {
                    if (second == 0) {
                        timeStr = minute + "m";
                    } else {
                        timeStr = minute + "m" + second + "s";
                    }
                }
            }
        } else {
            hour = minute / 60;
            minute = minute % 60;
            second = seconds - hour * 3600 - minute * 60;
            StringBuffer sb = new StringBuffer();
            if (hour != 0) {
                sb.append(hour + "h");
            }
            if (minute != 0) {
                sb.append(minute + "m");
            }
            if (second != 0) {
                sb.append(second + "s");
            }
            if (hour == 0 && minute == 0 && second == 0) {
                timeStr = "0";
            } else {
                timeStr = sb.toString();
            }
        }

        return timeStr;
    }

    /**
     * 时间转换  秒转分
     */
    public static String convertSecondToMin(int s) {

        String timeStr = null;
        int hour = 0;
        int minute = 0;
        int second = 0;

        minute = s / 60;
        if (minute < 60) {
            second = s % 60;
            timeStr = formatAddPre_0(minute) + ":" + formatAddPre_0(second);
        } else {
            hour = minute / 60;
            if (hour > 99)
                return "";
            minute = minute % 60;
            second = s - hour * 3600 - minute * 60;
            timeStr = formatAddPre_0(hour) + ":" + formatAddPre_0(minute) + ":" + formatAddPre_0(second);
        }

        return timeStr;
    }

    /**
     * 时间表示调整, 小于10, 前面添加0
     * @param i
     * @return
     */
    private static String formatAddPre_0(int i) {
        String retStr = null;
        if (i >= 0 && i < 10)
            retStr = "0" + i;
        else
            retStr = "" + i;
        return retStr;
    }

    /**
     * 判断时间是否通过
     *      ===> 结束时间大于等于开始时间
     * @param startTime
     * @param endTime
     * @param format 如yyyy-MM-dd HH:mm
     * @return
     */
    public static boolean isTimePass(String startTime, String endTime, String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        try {
            Date date1 = dateFormat.parse(startTime);//开始时间
            Date date2 = dateFormat.parse(endTime);//结束时间
            // 1 结束时间小于开始时间 2 开始时间与结束时间相同 3 结束时间大于开始时间
            if (date2.getTime() < date1.getTime()) {
                return false;
            } else if (date2.getTime() == date1.getTime()) {
                return true;
            } else if (date2.getTime() > date1.getTime()) {
                //正常情况下的逻辑操作.
                return true;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 格式化指定日期
     * @param originTime
     * @param calendarField
     * @param param
     * @param format
     * @return
     */
    public static String getFormatSpecDate(long originTime, int calendarField, int param, String format) {
        return formatDate(getSpecDate(originTime, calendarField, param), format);
    }

    /**
     * 获取指定时间戳的 param 差时间戳
     * @param originTime
     * @param calendarField 如以下传参
     *      年 Calendar.YEAR
     *      月 Calendar.MONTH (结果需+1),
     *      日 Calendar.DAY_OF_MONTH
     *      时 Calendar.HOUR_OF_DAY
     *      分 Calendar.MINUTE
     *      秒 Calendar.SECOND
     * @param param 时间差, 如前一天 -1, 后3天 3等
     * @return
     */
    public static Date getSpecDate(long originTime, int calendarField, int param) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(originTime);
        cal.add(calendarField, param);
        return cal.getTime();
    }

    /**
     * 根据传入time时间戳 获取指定time的时间段, 如何年, 月, 日, 时, 分, 秒...
     * @param time
     * @param calendarField 如以下传参
     *      年 Calendar.YEAR
     *      月 Calendar.MONTH (结果需+1),
     *      日 Calendar.DAY_OF_MONTH
     *      时 Calendar.HOUR_OF_DAY
     *      分 Calendar.MINUTE
     *      秒 Calendar.SECOND
     * @return
     */
    public static int getSpecTimeType(long time, int calendarField) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(time);
        if(calendarField == Calendar.MONTH) {
            return cal.get(calendarField) + 1;
        } else {
            return cal.get(calendarField);
        }
    }

    /**
     * 外国时间样式
     * 02-23-2022 , 11:01:43 AM
     * February-23-2022 , 11:01:43 AM
     * @param time
     * @param formatStyle 如 MM-dd-yyyy hh:mm:ss aa, MMMM-dd-yyyy , hh:mm:ss aa等
     * @return
     */
    public static String getForeignCountryTime(String time, String formatStyle) {
        if (AwDataUtil.isEmpty(time)) {
            return "";
        }
        Date date = new Date(Long.parseLong(time));
        //        SimpleDateFormat format = new SimpleDateFormat("MMMM-dd-yyyy , hh:mm:ss aa", Locale.US);
        SimpleDateFormat sdf = new SimpleDateFormat(formatStyle, Locale.ENGLISH);
        return formatDate(date, sdf);
    }

    /**
     * 判断是否在当前日期之后
     * @param paramTime
     * @return
     */
    public static boolean isAfterCurrentTime(String paramTime, String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);//年-月-日 时-分
        try {
            Date paramDate = dateFormat.parse(paramTime);//参数时间
            Date currentDate = new Date();//当前时间
            if (paramDate.getTime() < currentDate.getTime()) {
                //参数时间在当前时间之前
                return false;
            } else if (paramDate.getTime() == currentDate.getTime()) {
                return true;
            } else if (paramDate.getTime() > currentDate.getTime()) {
                //参数时间在当前时间之后
                return true;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获取过去第几天的日期
     *
     * @param past
     * @return
     */
    public static String getPastDate(int past) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - past);
        Date date = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat(FORMAT_YMD_HMS);
        String result = format.format(date);
        return result;
    }

    /**
     * 获取未来 第 past 天的日期
     *
     * @param past
     * @return
     */
    public static String getFetureDate(int past) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + past);
        Date today = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat(FORMAT_YMD_HMS);
        String result = format.format(today);
        return result;
    }

    /**
     * 获取某年某月第一天0点
     *
     * @param year
     * @param month
     * @return
     */
    public static long getFirstDayOfMonthStartTime(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, 1, 0, 0); // 设置为某月的第一天0点
        calendar.set(Calendar.MILLISECOND, 0); // 清除毫秒数
        return calendar.getTimeInMillis(); // 获取该时间的时间戳
    }

    /**
     * 获取某年某月最后一天12点
     *
     * @param year
     * @param month
     * @return
     */
    public static long getLastDayOfMonthEndTime(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, calendar.getActualMaximum(Calendar.DAY_OF_MONTH), 12, 0); // 设置为某月的最后一天12点
        calendar.set(Calendar.MILLISECOND, 0); // 清除毫秒数
        return calendar.getTimeInMillis(); // 获取该时间的时间戳
    }

    /**
     * 计算两个日期之间相差的时间戳数
     */
    private static long[] calculateDifference(Date startDate, Date endDate) {
        long differentMilliSeconds = endDate.getTime() - startDate.getTime();
        long secondsInMilli = 1000;//1s==1000ms
        long minutesInMilli = secondsInMilli * 60;
        long hoursInMilli = minutesInMilli * 60;
        long daysInMilli = hoursInMilli * 24;
        long elapsedDays = differentMilliSeconds / daysInMilli;
        differentMilliSeconds = differentMilliSeconds % daysInMilli;
        long elapsedHours = differentMilliSeconds / hoursInMilli;
        differentMilliSeconds = differentMilliSeconds % hoursInMilli;
        long elapsedMinutes = differentMilliSeconds / minutesInMilli;
        differentMilliSeconds = differentMilliSeconds % minutesInMilli;
        long elapsedSeconds = differentMilliSeconds / secondsInMilli;
        return new long[]{elapsedDays, elapsedHours, elapsedMinutes, elapsedSeconds};
    }

    /**
     * 计算每月的天数
     */
    public static int calculateDaysInMonth(int month) {
        return calculateDaysInMonth(0, month);
    }

    /**
     * 根据年份及月份计算每月的天数
     */
    public static int calculateDaysInMonth(int year, int month) {
        // 添加大小月月份并将其转换为list,方便之后的判断
        String[] bigMonths = {"1", "3", "5", "7", "8", "10", "12"};
        String[] littleMonths = {"4", "6", "9", "11"};
        List<String> bigList = Arrays.asList(bigMonths);
        List<String> littleList = Arrays.asList(littleMonths);
        // 判断大小月及是否闰年,用来确定"日"的数据
        if (bigList.contains(String.valueOf(month))) {
            return 31;
        } else if (littleList.contains(String.valueOf(month))) {
            return 30;
        } else {
            if (year <= 0) {
                return 29;
            }
            // 是否闰年
            if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
                return 29;
            } else {
                return 28;
            }
        }
    }

    /**
     * 月日时分秒，0-9前补0
     */
    public static String fillZero(int number) {
        return number < 10 ? "0" + number : "" + number;
    }

    /**
     * 截取掉前缀0以便转换为整数
     *
     * @see #fillZero(int)
     */
    public static int trimZero(String text) {
        try {
            if (text.startsWith("0")) {
                text = text.substring(1);
            }
            return Integer.parseInt(text);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return 0;
        }
    }

}
